#include "dispatcher.h"
#include "codec.h"

#include "muduo/base/Logging.h"
#include "muduo/base/Mutex.h"
// #include "muduo/net/EventLoop.h"
#include"muduo/net/EventLoopThread.h"//改
#include "muduo/net/TcpClient.h"

#include"dict.pb.h"
#include <stdio.h>
#include <unistd.h>

using namespace muduo;
using namespace muduo::net;


typedef std::shared_ptr<dict::AddResponse> Addresp;
typedef std::shared_ptr<dict::TransResponse> Transresp;

// typedef std::shared_ptr<dict::AddRequest> Addreqptr;

google::protobuf::Message* messageToSend;

class QueryClient : noncopyable
{
 public:
  QueryClient(const std::string& ip,const int& port)
  :client_(loop_.startLoop(), InetAddress(ip,port), "QueryClient"),
    latch_(1),
    dispatcher_(std::bind(&QueryClient::onUnknownMessage, this, _1, _2, _3)),
    codec_(std::bind(&ProtobufDispatcher::onProtobufMessage, &dispatcher_, _1, _2, _3))
  {

    dispatcher_.registerMessageCallback<dict::AddResponse>(
        std::bind(&QueryClient::onAddResponse, this, _1, _2, _3));
    dispatcher_.registerMessageCallback<dict::TransResponse>(
        std::bind(&QueryClient::onTransResponse, this, _1, _2, _3));
        
    client_.setConnectionCallback(
        std::bind(&QueryClient::onConnection, this, _1));
    client_.setMessageCallback(
        std::bind(&ProtobufCodec::onMessage, &codec_, _1, _2, _3));
  }

  void connect()
  {
    client_.connect();
    latch_.wait();
  }

  void SendAdd(int num1,int num2){
    dict::AddRequest addreq;
    // Addreqptr addreqp;
    addreq.set_num1(num1);
    addreq.set_num2(num2);
    messageToSend = &addreq;
    codec_.send(conn_, *messageToSend);

  }

    void Sendtrans(const std::string& word){
      dict::TransRequest transreq;
      transreq.set_msg(word);
      messageToSend = &transreq;
      codec_.send(conn_, *messageToSend);
    // conn_->send(addreq);

  }

 private:

  void onConnection(const TcpConnectionPtr& conn)
  {
    LOG_INFO << conn->localAddress().toIpPort() << " -> "
        << conn->peerAddress().toIpPort() << " is "
        << (conn->connected() ? "UP" : "DOWN");
    if (conn->connected())
    {

      // codec_.send(conn, *messageToSend);
      LOG_INFO<<"connect success";
      latch_.countDown();
      conn_ = conn;
    }
    else
    {
      LOG_ERROR<<"connection false";
      // loop_.quit()
    }
  }



  void onUnknownMessage(const TcpConnectionPtr&,
                        const MessagePtr& message,
                        Timestamp)
  {
    LOG_INFO << "onUnknownMessage: " << message->GetTypeName();
  }

  void onAddResponse(const muduo::net::TcpConnectionPtr&,
                const Addresp& message,
                muduo::Timestamp)
  {
                int num = message->num();
                LOG_INFO<<"Sum is "<<num;
    
  }

  void onTransResponse(const muduo::net::TcpConnectionPtr&,
               const Transresp& message,
               muduo::Timestamp)
  {
                std::string translation = message->msg();
                LOG_INFO<<"translation is "<<translation;

    // LOG_INFO << "onEmpty: " << message->GetTypeName();
  }

  // EventLoop* loop_;
  // EventLoopThreadPool loop_;
  TcpConnectionPtr conn_;
  EventLoopThread loop_;
  TcpClient client_;
  ProtobufDispatcher dispatcher_;
  ProtobufCodec codec_;
  muduo::CountDownLatch latch_;
};

int main(int argc, char* argv[]){
    std::string ip = "127.0.0.1";
    int port = 8080;
    // dict::AddRequest addreq;
    // addreq.set_num1(11);
    // addreq.set_num2(23);
    // messageToSend = &addreq;
    QueryClient client(ip,port);
    client.connect();
    while(1){
      std::string word;
      std::cin>>word;
      client.Sendtrans(word);
    }
    // sleep(5);
    std::cout<<"exit client\n";
    return 0;

}


// int main(int argc, char* argv[])
// {
//   LOG_INFO << "pid = " << getpid();
//   if (argc > 2)
//   {
//     EventLoop loop;
//     uint16_t port = static_cast<uint16_t>(atoi(argv[2]));
//     InetAddress serverAddr(argv[1], port);

//     muduo::Query query;
//     query.set_id(1);
//     query.set_questioner("Chen Shuo");
//     query.add_question("Running?");
//     muduo::Empty empty;
//     messageToSend = &query;

//     if (argc > 3 && argv[3][0] == 'e')
//     {
//       messageToSend = &empty;
//     }

//     QueryClient client(&loop, serverAddr);
//     client.connect();
//     loop.loop();
//   }
//   else
//   {
//     printf("Usage: %s host_ip port [q|e]\n", argv[0]);
//   }
// }

